<template>
  <div>
    <el-drawer v-bind="$attrs" v-on="$listeners" @opened="onOpen" @close="onClose">
      <div class="action-bar" :style="{'text-align': 'left'}">
        <span class="bar-btn" @click="refresh">
          <i class="el-icon-refresh" />
          刷新
        </span>
        <span ref="copyBtn" class="bar-btn copy-json-btn">
          <i class="el-icon-document-copy" />
          复制JSON
        </span>
        <span class="bar-btn" @click="exportJsonFile">
          <i class="el-icon-download" />
          导出JSON文件
        </span>
        <span class="bar-btn delete-btn" @click="$emit('update:visible', false)">
          <i class="el-icon-circle-close" />
          关闭
        </span>
      </div>
      <div id="editorJson" class="json-editor" />
    </el-drawer>
  </div>
</template>

<script>
  import { beautifierConf } from '@/utils/index'
  import ClipboardJS from 'clipboard'
  import { saveAs } from 'file-saver'
  import loadMonaco from '@/utils/loadMonaco'
  import loadBeautifier from '@/utils/loadBeautifier'

  let beautifier
  let monaco

  export default {
    components: {},
    props: {
      jsonStr: {
        type: String,
        required: true
      }
    },
    data() {
      return {}
    },
    computed: {},
    watch: {},
    created() {},
    mounted() {
      window.addEventListener('keydown', this.preventDefaultSave)
      const clipboard = new ClipboardJS('.copy-json-btn', {
        text: trigger => {
          this.$notify({
            title: '成功',
            message: '代码已复制到剪切板，可粘贴。',
            type: 'success'
          })
          return this.beautifierJson
        }
      })
      clipboard.on('error', e => {
        this.$message.error('代码复制失败')
      })
    },
    beforeDestroy() {
      window.removeEventListener('keydown', this.preventDefaultSave)
    },
    methods: {
      preventDefaultSave(e) {
        if (e.key === 's' && (e.metaKey || e.ctrlKey)) {
          e.preventDefault()
        }
      },
      onOpen() {
        loadBeautifier(btf => {
          beautifier = btf
          this.beautifierJson = beautifier.js(this.jsonStr, beautifierConf.js)

          loadMonaco(val => {
            monaco = val
            this.setEditorValue('editorJson', this.beautifierJson)
          })
        })
      },
      onClose() {},
      setEditorValue(id, codeStr) {
        if (this.jsonEditor) {
          this.jsonEditor.setValue(codeStr)
        } else {
          this.jsonEditor = monaco.editor.create(document.getElementById(id), {
            value: codeStr,
            theme: 'vs-dark',
            language: 'json',
            automaticLayout: true
          })
          // ctrl + s 刷新
          this.jsonEditor.onKeyDown(e => {
            if (e.keyCode === 49 && (e.metaKey || e.ctrlKey)) {
              this.refresh()
            }
          })
        }
      },
      exportJsonFile() {
        this.$prompt('文件名:', '导出文件', {
          inputValue: `${+new Date()}.json`,
          closeOnClickModal: false,
          inputPlaceholder: '请输入文件名'
        }).then(({ value }) => {
          if (!value) value = `${+new Date()}.json`
          const codeStr = this.jsonEditor.getValue()
          const blob = new Blob([codeStr], { type: 'text/plain;charset=utf-8' })
          saveAs(blob, value)
        })
      },
      refresh() {
        try {
          this.$emit('refresh', JSON.parse(this.jsonEditor.getValue()))
        } catch (error) {
          this.$notify({
            title: '错误',
            message: 'JSON格式错误，请检查',
            type: 'error'
          })
        }
      }
    }
  }
</script>

<style lang="scss" scoped>
  @import '@/styles/mixin.scss';

  ::v-deep .el-drawer__header {
    display: none;
  }
  @include action-bar;

  .json-editor{
    height: calc(100vh - 33px);
  }
</style>
